/**
 * Copyright (c) 2013 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners. 
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.composedui.model;

import java.util.Vector;

import com.nokia.example.composedui.utils.AppDataStorage;

/**
 * This class manages the persistency of the model content. Note that the
 * persistency of the application state is NOT managed by this class.
 */
public class ItemStorage implements DataItemListener {
    // Constants
    private static final int NUMBER_OF_SAMPLE_ITEMS = 22;
    private static final String STORAGE_ID_FOR_NUMBER_OF_ITEMS = "numberOfItems";
    private static final String STORAGE_ID_FOR_ITEM_NAME = "dataItemName";
    private static final String STORAGE_ID_FOR_ITEM_IMAGE_FILENAME = "dataItemImageFileName";
    private static final String STORAGE_ID_FOR_ACTIVE_ITEM_INDEX = "indexOfActiveDataItem";

    // Members
    private final AppDataStorage appDataStorage;
    private Vector dataItems;
    private DataItem activeDataItem;
    private Vector itemStorageListeners;

    /**
     * Constructor.
     * @param appDataStorage
     */
    public ItemStorage(AppDataStorage appDataStorage) {
        this.appDataStorage = appDataStorage;
        itemStorageListeners = new Vector();
        dataItems = new Vector();
        
        loadItemsFromAppDataStorage();
        
        if (dataItems.size() == 0) {
            System.out.println("ItemStorage::ItemStorage(): No items in the storage. Generating sample items.");
            generateSampleDataItems();
        }
        
        notifyItemStorageListeners();
    }

    /**
     * Saves the data items i.e. the model content to the storage.
     * @param saveImmediately If false, the content will be stored only in the
     * application memory to be saved permanently later. If true, will save
     * the content immediately to the persistent memory.
     */
    public void saveItemsToAppDataStorage(boolean saveImmediately) {
        appDataStorage.put(STORAGE_ID_FOR_NUMBER_OF_ITEMS, "" + dataItems.size());
        
        for (int i = 0; i < dataItems.size(); i++) {
            DataItem item = (DataItem)dataItems.elementAt(i);
            
            if (item != null) {
                appDataStorage.put(STORAGE_ID_FOR_ITEM_NAME + i, item.getName());
                appDataStorage.put(STORAGE_ID_FOR_ITEM_IMAGE_FILENAME + i,
                                   item.getImageFileName());
            }
            else {
                System.out.println("ItemStorage::saveItemsToAppDataStorage(): "
                    + "Warning: An item in the container is null!");
            }
        }
        
        if (activeDataItem != null) {
            appDataStorage.put(STORAGE_ID_FOR_ACTIVE_ITEM_INDEX,
                               String.valueOf(dataItems.indexOf(activeDataItem)));
        }
        
        if (saveImmediately) {
            appDataStorage.save(true);
        }
    }

    /**
     * Loads the stored data items i.e. the model content from the storage.
     */
    private void loadItemsFromAppDataStorage() {
        String numberOfItemsStr =
            appDataStorage.valueByKey(STORAGE_ID_FOR_NUMBER_OF_ITEMS);
        
        if (numberOfItemsStr != null) {
            int numberOfItems = Integer.parseInt(numberOfItemsStr);
            
            for (int i = 0; i < numberOfItems; i++) {
                String name = appDataStorage.valueByKey(STORAGE_ID_FOR_ITEM_NAME + i);
                String imageFileName =
                    appDataStorage.valueByKey(STORAGE_ID_FOR_ITEM_IMAGE_FILENAME + i);
                addElement(new DataItem(name, imageFileName));
            }
        }
        
        String activeDataItemIndexStr =
            appDataStorage.valueByKey(STORAGE_ID_FOR_ACTIVE_ITEM_INDEX);
        
        if (activeDataItemIndexStr != null) {
            int activeDataItemIndex = Integer.parseInt(activeDataItemIndexStr);
            
            if (activeDataItemIndex >= 0
                && activeDataItemIndex < dataItems.size())
            {
                activeDataItem =
                    (DataItem)dataItems.elementAt(activeDataItemIndex);
            }
        }
    }

    public void setActiveDataItem(DataItem dataItem) {
        activeDataItem = dataItem;
    }

    public void clearActiveDataItem() {
        activeDataItem = null;
    }

    public DataItem getActiveDataItem() {
        return activeDataItem;
    }


    // Observable design pattern implementation

    public void addItemStorageListener(ItemStorageListener listener) {
        if (itemStorageListeners.contains(listener) == false) {
            itemStorageListeners.addElement(listener);
            
            if (dataItems.size() > 0) {
                listener.dataChanged(dataItems);
            }
        }
    }

    public void removeItemStorageListener(ItemStorageListener listener) {
        if (itemStorageListeners.contains(listener)) {
            itemStorageListeners.removeElement(listener);
        }
    }

    public void notifyItemStorageListeners() {
        for (int i = 0; i < itemStorageListeners.size(); i++) {
            ((ItemStorageListener) itemStorageListeners.elementAt(i))
                    .dataChanged(dataItems);
        }
    }


    // Some element (data item) handling methods

    public Vector elements() {
        return dataItems;
    }

    public void addElement(DataItem dataItem) {
        dataItem.addDataItemListener(this);
        dataItems.addElement(dataItem);
        notifyItemStorageListeners();
    }

    public DataItem elementAt(int index) {
        return (DataItem) dataItems.elementAt(index);
    }

    public void removeElement(DataItem dataItem) {
        removeElement(dataItem, true);
    }

    public void removeElement(DataItem dataItem, boolean notify) {
        dataItems.removeElement(dataItem);
        
        if (notify) {
            notifyItemStorageListeners();
        }
    }

    public void removeElementAt(int index) {
        removeElementAt(index, true);
    }

    public void removeElementAt(int index, boolean notify) {
        dataItems.removeElementAt(index);
        
        if (notify) {
            notifyItemStorageListeners();
        }
    }

    public void itemDataChanged(DataItem dataItem) {
        notifyItemStorageListeners();
    }

    /**
     * Generates predefined number of sample data items to the model. 
     */
    private void generateSampleDataItems() {
        for (int i = 1; i <= NUMBER_OF_SAMPLE_ITEMS; i++) {
            String name = "Item " + i;
            String filename = "/avatar-" + (i % 2 == 0 ? "fe" : "") + "male.png";
            addElement(new DataItem(name, filename));
        }
    }
}
